package com.synjones.handsetS8.pages;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.synjones.handsetS8.Utils.util;
import com.synjones.handsetS8.ild.net.api.HandSetApi;
import com.synjones.handsetS8.R;;
import com.synjones.m1card.M1CardInfo;
import com.synjones.m1card.M1CardReader;
import com.synjones.reader.IDCardReaderModule;

import java.util.HashMap;
import java.util.Map;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;


public class ReadM1CardActivity extends Activity {
    private Button BtnFindCard;
    private Button BtnVerifyKeyA;
    private Button BtnVerifyKeyB;
    private Button BtnReadBlock;
    private Button BtnWrite;
    private Button BtnPending;
    private Button BtnClear;
    private ScrollView svResult;
    //private Button BtnWriteBlocks;
    //private Button BtnReadBlocks;
    private TextView tvMsg;

    private static final String TAG = "M1Card";
    IDCardReaderModule idCardReaderModule;
    boolean isConnect;
    long time = 0;
    final int MESSAGE_FIND_CARD = 0x51;
    boolean findingCard = false;
    Activity activity;
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_FIND_CARD:
                    BtnFindCard.setEnabled(true);
                    // beep();
                    //Toast.makeText(activity, "find a Card", Toast.LENGTH_SHORT).show();
                    M1CardInfo m1CardInfo = (M1CardInfo) msg.obj;
                    if (m1CardInfo != null) {
                        tvMsg.append("寻卡成功！\r\n");
                        TextView tvStatus = (TextView) activity.findViewById(R.id.tvStatus);
                        tvStatus.setText(m1CardInfo.toString());
                        //通过网络汇报数据
                        reportData(m1CardInfo);
                    } else
                        tvMsg.append("寻卡失败！\r\n");
                    scroll();
                    break;
            }
        }
    };

    /**
     * 通过网络汇报数据
     *
     * @param m1CardInfo
     */
    private void reportData(M1CardInfo m1CardInfo) {
        Map<String, Object> nfcInfo = new HashMap<>(16);
        nfcInfo.put("setNo", m1CardInfo.getCardNoStr());
        nfcInfo.put("bizCode", "LEARN_SIGN");

        HandSetApi.reportNfcInfo(nfcInfo, callback);
    }

    /**
     * 网络请求的回调接口
     */
    private Callback<ResponseBody> callback = new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            System.out.println(response.body());
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            System.out.println("请求失败");
        }
    };


    public ReadM1CardActivity() {
        // Required empty public constructor
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_read_m1_card);
        initViews();
    }

    public void initViews() {
        time = System.currentTimeMillis();
        activity = this;
        svResult = (ScrollView) findViewById(R.id.scrollMsg);
        BtnFindCard = (Button) activity.findViewById(R.id.btnFind);
        BtnVerifyKeyA = (Button) activity.findViewById(R.id.btnVerifyKeyA);
        BtnVerifyKeyB = (Button) activity.findViewById(R.id.btnVerifyKeyB);
        BtnReadBlock = (Button) activity.findViewById(R.id.btnReadblock);
        BtnWrite = (Button) activity.findViewById(R.id.btnWrite);
        BtnClear = (Button) activity.findViewById(R.id.btnClear);
        BtnPending = (Button) activity.findViewById(R.id.btnPending);
        //BtnWriteBlocks=(Button) activity.findViewById(R.id.btnWriteBlocks);
        //BtnReadBlocks=(Button) activity.findViewById(R.id.btnReadBlocks);
        tvMsg = (TextView) activity.findViewById(R.id.tvMsg);
        //MainActivity.Reader.getReaderDriver().EnterWorkModeNoReply();
        idCardReaderModule = IDCardReaderModule.getInstance(this);
        isConnect = idCardReaderModule.isOpen();

        if (!isConnect) {
            idCardReaderModule.open();
        }
        isConnect = idCardReaderModule.isOpen();

        BtnFindCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FindCard(5000);
                BtnFindCard.setEnabled(false);
            }
        });

        BtnVerifyKeyA.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                //if(!findCard(500)) return;
                boolean ret = DownloadKey(M1CardReader.KeyType.KeyA, getBlock(), getKey());
                tvMsg.append(ret ? "验证成功" : getRedText("验证失败"));
                scroll();
            }
        });
        BtnVerifyKeyB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                //ReadBlock(getBlock(),getKey(),KeyTypeB);
                // if(!findCard(500)) return;
                boolean ret = DownloadKey(M1CardReader.KeyType.KeyB, getBlock(), getKey());
                tvMsg.append(ret ? "验证成功" : getRedText("验证失败"));
                scroll();
            }
        });

        BtnReadBlock.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                long t = System.currentTimeMillis();
                byte reta[] = ReadBlock(getBlock());
                if (reta != null)
                    tvMsg.append(util.bytesToHexString(reta));
                else
                    tvMsg.append(getRedText("读失败"));
                tvMsg.append("用时：" + (System.currentTimeMillis() - t) + "\r\n");
                scroll();
            }
        });
        BtnWrite.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                boolean ret = WriteBlock(getBlock(), getWritedata());
                tvMsg.append("写块 " + getBlock() + "结果：" + (ret == true ? "成功" : getRedText("失败" + "\r\n")));
                scroll();
            }
        });

        BtnPending.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                boolean ret = PendingCard();
                if (ret)
                    tvMsg.append("挂起成功");
                else
                    tvMsg.append(getRedText("挂起失败"));
                scroll();
            }
        });
        BtnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                tvMsg.setText("");
                TextView tvs = (TextView) activity.findViewById(R.id.tvStatus);
                tvs.setText("状态");
            }
        });

   /*    BtnWriteBlocks.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if(isConnect){
                    if(m1Reader==null)
                        m1Reader=new M1CardReader(multiReader);
                    writeBlocks();
                }
            }
        });

        BtnReadBlocks.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if(isConnect){
                    if(m1Reader==null)
                        m1Reader=new M1CardReader(multiReader);
                    readBlocks();
                }
            }
        });*/


    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }


    /**
     * 寻卡
     */
    public void FindCard(final int timeout) {
        findingCard = true;
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                M1CardInfo m1CardInfo = null;
                long t = System.currentTimeMillis();
                while (findingCard && System.currentTimeMillis() - t < timeout && m1CardInfo == null) {
                    m1CardInfo = idCardReaderModule.findM1Card();
                    if (m1CardInfo != null) {
                        mHandler.obtainMessage(MESSAGE_FIND_CARD, m1CardInfo).sendToTarget();
                        break;
                    }
                    util.sleep(50);
                }
                findingCard = false;
                if (m1CardInfo == null)
                    mHandler.obtainMessage(MESSAGE_FIND_CARD, null).sendToTarget();

            }
        }).start();
    }

    /**
     * 写卡
     *
     * @param blockNo 块号
     * @param data    16字节数据
     */
    public boolean WriteBlock(byte blockNo, byte data[]) {
        if (!isConnect) return false;
        return idCardReaderModule.writeBlock(blockNo, data);

    }


    /**
     * 获取界面上输入的KEY
     *
     * @return
     */
    public byte[] getKey() {
        byte key[] = new byte[6];
        EditText et;
        int KeyId = R.id.etKey0;
        for (int i = 0; i < 6; i++) {
            et = (EditText) activity.findViewById(KeyId + i);
            String hexStr = "0x" + et.getText().toString();
            try {
                int tmp = Integer.decode(hexStr);
                key[i] = (byte) (tmp & 0xff);
            } catch (Exception e) {
                String err = "getKey() err" + e.getMessage();
                d(this, err);
                Toast.makeText(activity, err, Toast.LENGTH_SHORT).show();

            }
        }
        return key;
    }

    /**
     * 获取界面上输入的data
     *
     * @return
     */

    public byte[] getWritedata() {
        int dataId[] = {R.id.etWriteData0, R.id.etWriteData1, R.id.etWriteData2, R.id.etWriteData3,
                R.id.etWriteData4, R.id.etWriteData5, R.id.etWriteData6, R.id.etWriteData7,
                R.id.etWriteData8, R.id.etWriteData9, R.id.etWriteData10, R.id.etWriteData11,
                R.id.etWriteData12, R.id.etWriteData13, R.id.etWriteData14, R.id.etWriteData15};
        byte Writedata[] = new byte[16];
        EditText et;
        //int dataId=R.id.etWriteData0;
        for (int i = 0; i < 16; i++) {
            et = (EditText) activity.findViewById(dataId[i]);
            String hexStr = "0x" + et.getText().toString();
            try {
                int tmp = Integer.decode(hexStr);
                Writedata[i] = (byte) (tmp & 0xff);
            } catch (Exception e) {
                String err = "getKey() err" + e.getMessage();
                d(this, err);
                Toast.makeText(activity, err, Toast.LENGTH_SHORT).show();

            }
        }
        return Writedata;
    }

    public static void d(Object o, String msg) {
        Log.d(TAG, o.getClass().getName() + " " + msg);
    }

    public static void e(Object o, String msg) {
        Log.e(TAG, o.getClass().getName() + " " + msg);
    }

    /**
     * 获取界面上的块号
     *
     * @return
     */
    public byte getBlock() {
        EditText et = (EditText) activity.findViewById(R.id.etBlock);
        String BlockStr = et.getText().toString();
        int tmp = 0;
        try {
            tmp = Integer.decode(BlockStr);
        } catch (Exception e) {
            d(this, "getKey() err" + e.getMessage());

        }
        return (byte) (tmp & 0xff);
    }

    private int getTestBlockNums() {
        EditText et = (EditText) activity.findViewById(R.id.etTestNums);
        String BlockStr = et.getText().toString();
        int tmp = 0;
        try {
            tmp = Integer.decode(BlockStr);
        } catch (Exception e) {
            d(this, "getKey() err" + e.getMessage());
        }
        return tmp;
    }


    /**
     * 显示卡片类型信息
     *
     * @param buf 接收到的数据buf
     * @param len 接收到的数据长度
     */
    public void showCardInfo(byte buf[], int len) {
        if (len > 0 && buf[0] == 0xa) {
            TextView tvStatus = (TextView) activity.findViewById(R.id.tvStatus);
            String status = "|卡号：" + bytesToHexString(getCardNo(buf), 4) + "|类型：" + bytesToHexString(getCardType(buf), 2)
                    + "|大小：" + bytesToHexString(getCardSize(buf), 1);
            tvStatus.setText(status);
        }
    }

    /**
     * 从寻卡返回的数据中获取卡号
     *
     * @param buf 接收到的数据
     * @return
     */
    public byte[] getCardNo(byte buf[]) {
        if (buf[0] == 0x03 || buf[0] != 0x0a) return null;
        byte cardNo[] = new byte[4];
        int cardNOoffset = 2;
        System.arraycopy(buf, cardNOoffset, cardNo, 0, cardNo.length);
        return cardNo;
    }

    /**
     * 获取卡片类型
     *
     * @param buf 接收到的数据
     * @return
     */
    public byte[] getCardType(byte buf[]) {
        if (buf[0] == 0x03 || buf[0] != 0x0a) return null;
        byte cardType[] = new byte[2];
        int cardTypeoffset = 6;
        System.arraycopy(buf, cardTypeoffset, cardType, 0, cardType.length);
        return cardType;
    }

    /**
     * 获取卡大小
     *
     * @param buf 接收到的数据
     * @return
     */
    public byte[] getCardSize(byte buf[]) {
        if (buf[0] == 0x03 || buf[0] != 0x0a) return null;
        int cardTypeoffset = 8;
        byte cardSize[] = new byte[1];
        cardSize[0] = buf[cardTypeoffset];
        return cardSize;
    }


    public void onResume() {
        d(this, TAG + "Enter onResume");
        super.onResume();
    }


    public static String bytesToHexString(byte[] src, int len) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < len; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            stringBuilder.append("0x");
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }

            stringBuilder.append(hv.toUpperCase());
            stringBuilder.append(",");
        }
        return stringBuilder.toString();
    }


    public boolean PendingCard() {
        if (!isConnect) return false;
        return idCardReaderModule.pend();
    }

    //下载密钥A
    public boolean DownloadKey(M1CardReader.KeyType keytype, byte block, byte key[]) {
        /*下载扇区密钥A*/
        if (!isConnect) return false;
        return idCardReaderModule.verifyKey(keytype, block, key);
    }


    /**
     * 读卡片上的block数据
     *
     * @param block 需要读取的block块
     * @return 读到的卡片上的块数据
     */
    public byte[] ReadBlock(byte block) {
        if (!isConnect) return null;
        return idCardReaderModule.readBlock(block);
    }

    public void scroll() {

        svResult.post(new Runnable() {
            public void run() {
                svResult.fullScroll(ScrollView.FOCUS_DOWN);
            }
        });
    }


    public void beep() {
        //byte cmdarray[]=packCMD(CMDtype.beep,null);
        //newserial.SendData(cmdarray, cmdarray.length);
        //if(Is_ok(recvdata,len))
        //Toast.makeText(getActivity(), "len="+len, Toast.LENGTH_SHORT).show();
        //tvMsg.append(bytesToHexString(data,dataLen));

    }
/*
    private void writeBlocks(){
        if(m1Reader==null) return;
        tvMsg.setText("");
        TextView tvs=(TextView) activity.findViewById(R.id.tvStatus);
        tvs.setText("状态");
        WriteBlocksAsync wba=new WriteBlocksAsync();
        wba.execute();
    }
    private void readBlocks(){
        if(m1Reader==null) return;
        tvMsg.setText("");
        TextView tvs=(TextView) activity.findViewById(R.id.tvStatus);
        tvs.setText("状态");
        ReadBlocksAsnnc rba=new ReadBlocksAsnnc();
        rba.execute();
    }*/

    private boolean findCard(long timeout) {
        long t = System.currentTimeMillis();
        //multiReader.EnterWorkMode();
        while (System.currentTimeMillis() - t < timeout) {
            M1CardInfo m1CardInfo = idCardReaderModule.findM1Card();
            if (m1CardInfo != null) {
                return true;
            }
            util.sleep(100);
        }
        return false;
    }


    private SpannableStringBuilder getRedText(String text) {
        return getColorText(text, Color.RED);
    }

    private SpannableStringBuilder getColorText(String text, int color) {
        SpannableStringBuilder builder = new SpannableStringBuilder(text);
        //ForegroundColorSpan 为文字前景色，BackgroundColorSpan为文字背景色 Color.RED
        ForegroundColorSpan redSpan = new ForegroundColorSpan(color);
        builder.setSpan(redSpan, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return builder;
    }

    /*private class ReadBlocksAsnnc extends AsyncTask<Void, Integer, Integer> {
        //byte readdata[][]=new byte[16][16];
        byte readBlockData[];
        long startTime;
        CmdResponse resp=null;
        int num=0;
        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            BtnReadBlocks.setEnabled(false);
            num=getTestBlockNums();
        }
        @Override
        protected Integer doInBackground(Void... arg0) {
            byte blockNo= getBlock();
            boolean needDownKey=true;
            boolean ret=false;
            byte key[]=getKey();
            startTime=System.currentTimeMillis();
            if(!findCard(1000))
                return -2;
            // m1Reader.beginTrans();
            for(int pos=0;pos<num;pos++){
                //genWriteData(pos);
                if((blockNo+1)%4==0){
                    blockNo++;
                    needDownKey=true;
                }
                //needDownKey=true;
                int intBlockNo=((int)blockNo)&0xff;
                publishProgress(0,intBlockNo);
                if(needDownKey){
                    ret=DownloadKey(M1CardReader.KeyType.KeyA, blockNo, key);
                    if(!ret) publishProgress(-1,intBlockNo);
                    needDownKey=false;
                }
                //long t1=System.currentTimeMillis();

                readBlockData=ReadBlock(blockNo);
                if(readBlockData!=null && verifyData(0,readBlockData)){
                    publishProgress(2,intBlockNo);
                }else{
                    publishProgress(1,intBlockNo);
                }
                blockNo++;
                //sleep(10);
            }
            long t1=System.currentTimeMillis();
            return 0;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
            switch (values[0]) {
                case -1:
                    tvMsg.append(getRedText("第"+values[1]+"块密钥验证失败\r\n"));
                    break;
                case 0:
                    tvMsg.append("第"+values[1]+"块测试读开始"+*//*bytesToHexString(writedata[pos],16)*//*"\r\n");
                    //Log.e("m1", "第"+values[1]+"块测试写开始"+bytesToHexString(writedata[pos],16)+"\r\n");
                    break;
                case 1:
                    tvMsg.append(getRedText("第"+values[1]+"块读出数据失败\r\n"));
                    break;
                case 2:
                    tvMsg.append("第"+values[1]+"块读卡成功,数据="+bytesToHexString(readBlockData,16)+"\r\n");
                    break;
                case 4:
                    tvMsg.append("用时："+values[1]+"mS\r\n");
                    break;
                default:
                    break;
            }
        }
        @Override
        protected void onPostExecute(Integer result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            BtnReadBlocks.setEnabled(true);
            super.onPostExecute(result);
            switch (result) {
                case 0:
                    tvMsg.append("测试结束\r\n"+"用时："+(System.currentTimeMillis()-startTime));
                    SparseArray<byte[]> readArray= m1Reader.getReadData(resp);
                    if(resp!=null){
                        tvMsg.append("\r\n数据="+bytesToHexString(resp.getData(), resp.getData().length)+"\r\n");
                    }
                    break;
                case -1:
                    tvMsg.append(getRedText("测试失败\r\n"));
                    break;
                case -2:
                    tvMsg.append(getRedText("寻卡失败"));
                    break;
                default:
                    break;
            }
        }

    }




    private class WriteBlocksAsync extends AsyncTask<Void, Integer, Integer>{
        private byte writedata[][]=new byte[16][16];
        private int pos;
        private long startTime;
        int num=0;
        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            BtnWriteBlocks.setEnabled(false);
            num=getTestBlockNums();
        }
        @Override
        protected Integer doInBackground(Void... arg0) {
            byte blockNo= getBlock();
            boolean needDownKey=true;
            boolean ret=false;
            byte key[]=getKey();
            startTime=System.currentTimeMillis();
            if(!findCard(1000))
                return -2;
            //m1Reader.beginTrans();
            for(pos=0;pos<num;pos++){
                //genWriteData(pos);
                if((blockNo+1)%4==0){
                    blockNo++;
                    needDownKey=true;
                }
                int intBlockNo=((int)blockNo)&0xff;
                publishProgress(0,intBlockNo);
                if(needDownKey){
                    ret=DownloadKey(M1CardReader.KeyType.KeyA, blockNo, key);
                    if(!ret) publishProgress(-1,intBlockNo);
                    needDownKey=false;
                }
                //	long t1=System.currentTimeMillis();
                ret=WriteBlock(blockNo,getWritedata());
                if(!ret) publishProgress(-2,intBlockNo);
                else publishProgress(3,intBlockNo);
                blockNo++;
                //sleep(10);
            }

            return 0;
        }
        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
            switch (values[0]) {
                case -1:
                    tvMsg.append(getRedText("第"+values[1]+"块密钥验证失败\r\n"));
                    break;
                case -2:
                    tvMsg.append(getRedText("第"+values[1]+"块写卡失败\r\n"));
                    break;
                case 0:
                    tvMsg.append("第"+values[1]+"块测试写开始"+*//*bytesToHexString(writedata[pos],16)*//*"\r\n");
                    //Log.e("m1", "第"+values[1]+"块测试写开始"+bytesToHexString(writedata[pos],16)+"\r\n");
                    break;
                case 3:
                    tvMsg.append("第"+values[1]+"块写卡成功\r\n");
                    break;
                case 4:
                    tvMsg.append("用时："+values[1]+"mS\r\n");
                    break;
                default:
                    break;
            }
        }

        @Override
        protected void onPostExecute(Integer result) {
            // TODO Auto-generated method stub
            BtnWriteBlocks.setEnabled(true);
            super.onPostExecute(result);
            switch (result) {
                case 0:
                    //CmdResponse resp=m1Reader.endTrans(1000);

                    tvMsg.append("测试结束\r\n"+"用时："+(System.currentTimeMillis()-startTime));
                    // if(resp!=null)
                    //     tvMsg.append("\r\n测试写成功\r\n");
                    break;
                case -1:
                    tvMsg.append(getRedText("测试失败\r\n"));
                    break;
                case -2:
                    tvMsg.append(getRedText("寻卡失败"));
                    break;
                default:
                    break;
            }
        }

        private void genWriteData(int index){
            for(int i=0;i<16;i++){
                writedata[index][i]=(byte) (Math.random()*256);
            }
        }


        private void sleep(long t) {
            try {
                Thread.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }*/

    private boolean verifyData(int index, byte data[]) {
        byte wd[] = getWritedata();
        for (int i = 0; i < 16; i++) {
            if (wd[i] != data[i])
                return false;
        }
        return true;
    }
}